<script setup lang="ts">
import { ref, unref, onMounted, onUnmounted, onActivated } from "vue";
import { Download, Plus, Upload } from "@element-plus/icons-vue";
import { serverExpandStorage, serverStorage } from "@/storage";
import { useRoute, useRouter } from "vue-router";
import { exportJson, importJson } from "@/utils/exportJson";
import { dayjs, ElMessage, ElNotification, UploadFile } from "element-plus";
import {
  getFtpItem,
  onSilenceBuildUpload,
  onStartExec,
  onZipPack,
} from "@/utils/upload";
import { emitter, openSelectDirectory } from "@/utils/mitt";
import {
  filterTree,
  generateUUID,
  getStringAfter,
  isNowColorClass,
  refreshFormatTime,
  toLinuxPath,
} from "@/utils";
import SvgFolder from "@/components/svg/SvgFolder.vue";
import ServerIndexDialog from "./component/ServerIndexDialog.vue";

const loading = ref(false);
const route = useRoute();
const router = useRouter();
const dialogRef = ref<typeof ServerIndexDialog>();

const handleEditRow = (row?: DeployFtpType) => {
  dialogRef.value?.open(row);
};

const handleRemoveRow = (data: WebType) => {
  // 过滤
  serverStorage.value = filterTree<WebType>(
    unref(serverStorage),
    (item) => item.id !== data.id
  );
  // 移除缓存的展开
  onNodeCollapse(data);
};

const handleUpload = (row: DeployFtpType) => {
  router.push({
    path: "/upload",
    query: {
      id: row.id,
      type: "server",
    },
  });
};

/**
 * 发布上传
 * @param row
 * @param alter 只传5分钟内变更的文件（不包含排除的文件）
 */
const handleBuildSilenceUpload = async (
  row: WebType,
  alter?: boolean | undefined
) => {
  if (loading.value) {
    ElMessage.warning("请等待执行结束。");
    return;
  }
  try {
    emitter.emit("showLoading", { text: "正在发布中..." });
    loading.value = true;
    await onSilenceBuildUpload(row, "server", alter);

    // 提示
    const message = `${row.title} - 上传完成。\n${row.target}\n`;
    ElNotification({
      title: "成功提示",
      message,
      type: "success",
      position: "bottom-left",
    });
    loading.value = false;
    emitter.emit("hideLoading");
  } catch (e) {
    const message = e ? String(e) : `\n${row.title} - 上传失败\n`;
    ElNotification({
      title: "错误提示",
      message,
      type: "error",
      position: "bottom-left",
    });
    loading.value = false;
    emitter.emit("hideLoading");
  }
};

const handleExportJson = () => {
  openSelectDirectory();
};

const handleImportJson = (file: UploadFile) => {
  importJson(file).then((json) => {
    if (json && json.length) {
      serverStorage.value = json;
    }
  });
};

/**
 * 文件管理
 * @param row
 */
const handleFile = (row: WebType) => {
  router.push({
    path: "/file",
    query: {
      id: row.id,
      type: "server",
    },
  });
};

const onAppend = (data: WebType) => {
  const newChild = {
    id: generateUUID(),
    title: data.title || "新增",
    ftp_id: "",
    target: "",
    source: "",
    exclude: [],
    writes: [],
    filename: "",
    children: [],
  };
  if (!data.children) {
    data.children = [];
  }
  data.children.push(newChild);
  serverStorage.value = [...serverStorage.value];
  // 默认展开
  onNodeExpand(data);
};

const onNodeExpand = (data: WebType) => {
  if (!serverExpandStorage.value.includes(data.id))
    serverExpandStorage.value.push(data.id);
};

const onNodeCollapse = (data: WebType) => {
  serverExpandStorage.value = serverExpandStorage.value.filter(
    (id) => id !== data.id
  );
};

/**
 * 获取host
 * @param data
 * @param after 是否只获取最后一个点后的数字
 */
const getFtpHost = (data: WebType, after?: boolean) => {
  const item = getFtpItem(data.ftp_id);
  if (after) {
    return item ? getStringAfter(item.host) : "";
  } else {
    return item ? item.host : "";
  }
};

/**
 * 压缩
 * @param alter 只传5分钟内变更的文件（不包含排除的文件）
 */
const onZip = async (data: WebType, alter?: boolean | undefined) => {
  try {
    loading.value = true;
    // 压缩
    const { output, target } = await onZipPack({
      web: data,
      alter,
      hash: true,
    });
    // 提示
    const message = `\n${data.title} - 压缩完成。\n${output}\n`;
    ElNotification({
      title: "成功提示",
      message,
      type: "success",
      position: "bottom-left",
    });
    console.log("target:", target);
    onStartExec(target);
    loading.value = false;
  } catch (e) {
    const message = e ? String(e) : `\n${data.title} - 压缩失败\n`;
    loading.value = false;
    ElNotification({
      title: "错误提示",
      message,
      type: "error",
      duration: 0,
    });
  }
};

const emitKey = `on-directory-${route.fullPath}`;
const emitVisibleKey = `on-visible-${route.fullPath}`;

onMounted(() => {
  emitter.on(emitKey, (localPath) => {
    const filename = `${route.meta.title || "data"}.json`;
    exportJson(localPath, unref(serverStorage), filename);
  });
  emitter.on(emitVisibleKey, (visible) => {
    if (visible) refreshFormatTime(unref(serverStorage));
  });
  refreshFormatTime(unref(serverStorage));
});

onUnmounted(() => {
  emitter.off(emitKey);
  emitter.off(emitVisibleKey);
});

onActivated(() => {
  refreshFormatTime(unref(serverStorage));
});
</script>

<template>
  <div class="container h100 flex flex-column">
    <div class="flex align-center">
      <el-button plain type="primary" :icon="Plus" @click="handleEditRow()"
        >新增一行</el-button
      >
      <el-button plain type="info" :icon="Download" @click="handleExportJson()"
        >导出JSON</el-button
      >
      <el-upload
        :auto-upload="false"
        @change="handleImportJson"
        :show-file-list="false"
      >
        <el-button plain type="warning" :icon="Upload" class="ml5"
          >导入JSON</el-button
        >
      </el-upload>
    </div>
    <el-scrollbar class="flex-grow-1">
      <el-tree
        :data="serverStorage"
        node-key="id"
        draggable
        :auto-expand-parent="false"
        :default-expanded-keys="serverExpandStorage"
        @node-expand="onNodeExpand"
        @node-collapse="onNodeCollapse"
        :expand-on-click-node="false"
      >
        <template #default="{ data }">
          <div
            class="custom-tree-node flex-grow-1 flex align-center font-12"
            style="width: 100%"
          >
            <SvgFolder v-if="data.children?.length" class="directory" />
            <el-tooltip
              v-else
              :content="`${data.title} ${getFtpHost(data)} ${toLinuxPath(
                `${data.target}/${data.filename}`
              )}`"
              placement="right"
            >
              <img class="directory" src="@/assets/icons/config.png" alt="" />
            </el-tooltip>
            <div style="min-width: 30%" class="flex align-center ml3">
              <span>{{ data.title }}</span>
              <span class="ml3 color-info" v-if="!data.children?.length">{{
                getFtpHost(data, true)
              }}</span>
              <span v-if="data.filename" class="color-danger ml3">{{
                data.filename
              }}</span>
              <span
                v-if="
                  !(data.children && data.children.length) &&
                  (!data.ftp_id || !data.target || !data.source)
                "
                class="color-danger"
                >（未编辑状态）</span
              >
            </div>
            <div class="flex align-center">
              <el-button link @click.prevent="onAppend(data)" :icon="Plus" />
              <el-button
                link
                type="danger"
                @click.prevent="handleRemoveRow(data)"
                class="ml0"
              >
                删除
              </el-button>
              <el-button
                link
                type="primary"
                @click.prevent="handleEditRow(data)"
                class="ml0"
              >
                编辑
              </el-button>
              <template v-if="!data.children?.length">
                <el-button
                  link
                  type="success"
                  @click.prevent="handleUpload(data)"
                  class="ml0"
                >
                  连接
                </el-button>
                <el-button
                  link
                  type="info"
                  @click.prevent="onZip(data, true)"
                  :disabled="loading"
                  class="ml0"
                >
                  生成变更压缩包
                </el-button>
                <el-button
                  link
                  type="info"
                  @click.prevent="handleFile(data)"
                  class="ml0"
                >
                  文件
                </el-button>
                <el-button
                  link
                  type="info"
                  @click.prevent="handleBuildSilenceUpload(data)"
                  :disabled="loading"
                  class="ml0"
                >
                  发布上传
                </el-button>
                <el-button
                  link
                  type="warning"
                  @click.prevent="handleBuildSilenceUpload(data, true)"
                  :disabled="loading"
                  class="ml0"
                >
                  变更上传
                </el-button>
                <el-tooltip
                  v-if="data.time"
                  :content="dayjs(data.time).format('YYYY-MM-DD HH:mm:ss')"
                  placement="top-start"
                >
                  <span class="ml5 mr5" :class="isNowColorClass(data.time)">
                    · 更新于 {{ data.time_string }} ·
                  </span>
                </el-tooltip>
              </template>
            </div>
          </div>
        </template>
      </el-tree>
      <div style="height: 50px; width: 100%"></div>
    </el-scrollbar>
    <ServerIndexDialog ref="dialogRef" />
  </div>
</template>
